/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
package pw.yumc.Residence;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

import com.bekvon.bukkit.residence.Residence;
import com.bekvon.bukkit.residence.event.ResidenceCommandEvent;
import com.bekvon.bukkit.residence.permissions.PermissionManager;
import com.bekvon.bukkit.residence.protection.ClaimedResidence;
import com.bekvon.bukkit.residence.protection.FlagPermissions;
import com.bekvon.bukkit.residence.protection.LeaseManager;
import com.bekvon.bukkit.residence.protection.PermissionListManager;
import com.bekvon.bukkit.residence.protection.ResidenceManager;
import com.bekvon.bukkit.residence.protection.WorldFlagManager;
import com.earth2me.essentials.Essentials;

import cn.citycraft.PluginHelper.commands.HandlerMainCommand;
import cn.citycraft.PluginHelper.config.FileConfig;
import cn.citycraft.PluginHelper.utils.CompatibleUtil;
import cn.citycraft.PluginHelper.utils.VersionChecker;
import pw.yumc.Residence.chat.ChatManager;
import pw.yumc.Residence.commandmain.CommandRc;
import pw.yumc.Residence.commandmain.CommandRes;
import pw.yumc.Residence.commandmain.CommandResLoad;
import pw.yumc.Residence.commandmain.CommandResReload;
import pw.yumc.Residence.commandmain.CommandResWorld;
import pw.yumc.Residence.economy.EconomyInterface;
import pw.yumc.Residence.economy.EssentialsEcoAdapter;
import pw.yumc.Residence.economy.TransactionManager;
import pw.yumc.Residence.economy.rent.RentManager;
import pw.yumc.Residence.gui.FlagUtil;
import pw.yumc.Residence.itemlist.WorldItemManager;
import pw.yumc.Residence.listeners.ResidenceBlockListener;
import pw.yumc.Residence.listeners.ResidenceEntityListener;
import pw.yumc.Residence.listeners.ResidenceGUIListener;
import pw.yumc.Residence.listeners.ResidencePlayerListener;
import pw.yumc.Residence.listeners.ResidencePlayerListener_1_8;
import pw.yumc.Residence.listeners.bugfix.ResidenceBugFix;
import pw.yumc.Residence.manager.ConfigManager;
import pw.yumc.Residence.manager.EntityManager;
import pw.yumc.Residence.persistance.YMLSaveHelper;
import pw.yumc.Residence.runnable.AutoSaveTask;
import pw.yumc.Residence.runnable.HealTask;
import pw.yumc.Residence.runnable.LeaseTask;
import pw.yumc.Residence.runnable.RentTask;
import pw.yumc.Residence.runnable.TaskManager;
import pw.yumc.Residence.selection.SelectionManager;
import pw.yumc.Residence.selection.WorldEditSelectionManager;
import pw.yumc.Residence.text.Language;
import pw.yumc.Residence.text.help.HelpEntry;
import pw.yumc.Residence.text.help.InformationPager;
import pw.yumc.Residence.utils.DataBackup;
import pw.yumc.Residence.vaultinterface.ResidenceVaultAdapter;

/**
 *
 * @author Gary Smoak - bekvon
 *
 */
public class ResidenceMain extends JavaPlugin {

    public final static int saveVersion = 1;
    public final static String[] validLanguages = { "English", "Chinese" };
    public final static Pattern VER_REGEX = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)");
    protected static ResidenceMain instance;

    private ConfigManager cmanager;
    private boolean vergt1_8;

    protected DataBackup backup;
    protected ChatManager chatmanager;
    protected FileConfig config;
    protected FileConfig deny;
    protected File dataFolder;
    protected Map<String, String> deleteConfirm;
    protected EconomyInterface economy;
    protected ResidenceEntityListener elistener;
    protected EntityManager entitymanager;
    protected PermissionManager gmanager;
    protected HandlerMainCommand hdmcnd;
    protected HelpEntry helppages;
    protected WorldItemManager imanager;
    protected boolean init;
    protected Language language;
    protected LeaseManager leasemanager;
    protected ResidenceBlockListener blistener;
    protected ResidencePlayerListener plistener;
    protected ResidencePlayerListener_1_8 plistener1_8;
    protected ResidenceGUIListener glistener;
    protected PermissionListManager pmanager;
    protected RentManager rentmanager;
    protected List<String> resadminToggle;
    protected ResidenceManager rmanager;
    protected SelectionManager smanager;
    protected TaskManager taskmanager;
    protected TransactionManager tmanager;
    protected boolean useWorldEdit;
    protected WorldFlagManager wmanager;
    protected FlagUtil fmanager;

    public static ResidenceMain getInstance() {
        return instance;
    }

    public void csm(final String... msgs) {
        for (final String msg : msgs) {
            Bukkit.getConsoleSender().sendMessage("§6[§a领地插件§6]§r " + msg);
        }
    }

    public DataBackup getBackup() {
        return backup;
    }

    public ResidenceBlockListener getBlockListener() {
        return blistener;
    }

    public ChatManager getChatManager() {
        return chatmanager;
    }

    @Override
    public FileConfiguration getConfig() {
        return config;
    }

    public ConfigManager getConfigManager() {
        return cmanager;
    }

    public File getDataLocation() {
        return dataFolder;
    }

    public Map<String, String> getDeleteConfirm() {
        return deleteConfirm;
    }

    /**
     * @return the deny
     */
    public FileConfig getDeny() {
        return deny;
    }

    public EconomyInterface getEconomyManager() {
        return economy;
    }

    public ResidenceEntityListener getEntityListener() {
        return elistener;
    }

    public EntityManager getEntityManager() {
        return entitymanager;
    }

    public FlagUtil getFlagUtilManager() {
        return fmanager;
    }

    public HelpEntry getHelppages() {
        return helppages;
    }

    public WorldItemManager getItemManager() {
        return imanager;
    }

    public Language getLanguage() {
        if (language == null) {
            language = new Language();
        }
        return language;
    }

    public LeaseManager getLeaseManager() {
        return leasemanager;
    }

    public PermissionListManager getPermissionListManager() {
        return pmanager;
    }

    public PermissionManager getPermissionManager() {
        return gmanager;
    }

    public FlagPermissions getPermsByLoc(final Location loc) {
        final ClaimedResidence res = rmanager.getByLoc(loc);
        if (res != null) {
            return res.getPermissions();
        }
        return wmanager.getPerms(loc.getWorld().getName());
    }

    public FlagPermissions getPermsByLocForPlayer(final Location loc, final Player player) {
        final ClaimedResidence res = rmanager.getByLoc(loc);
        if (res != null) {
            return res.getPermissions();
        } else if (player != null) {
            return wmanager.getPerms(player);
        } else {
            return wmanager.getPerms(loc.getWorld().getName());
        }
    }

    public ResidencePlayerListener getPlayerListener() {
        return plistener;
    }

    public RentManager getRentManager() {
        return rentmanager;
    }

    public List<String> getResadminToggle() {
        return resadminToggle;
    }

    public ResidenceManager getResidenceManager() {
        return rmanager;
    }

    public SelectionManager getSelectionManager() {
        return smanager;
    }

    public TransactionManager getTransactionManager() {
        return tmanager;
    }

    public WorldFlagManager getWorldFlags() {
        return wmanager;
    }

    public boolean isGt1_8() {
        return vergt1_8;
    }

    public boolean isInit() {
        return init;
    }

    public boolean isResAdminOn(final Player player) {
        if (resadminToggle.contains(player.getName())) {
            return true;
        }
        return false;
    }

    public boolean isResAdminOn(final String player) {
        if (resadminToggle.contains(player.toLowerCase())) {
            return true;
        }
        return false;
    }

    public boolean isUseWorldEdit() {
        return useWorldEdit;
    }

    public void loadLang(final File langFile) throws FileNotFoundException, IOException, InvalidConfigurationException {
        final FileConfig langconfig = new FileConfig(this, langFile);
        helppages = HelpEntry.parseHelp(this, langconfig, "CommandHelp");
        HelpEntry.setLinesPerPage(langconfig.getInt("HelpLinesPerPage", 7));
        InformationPager.setLinesPerPage(langconfig.getInt("HelpLinesPerPage", 7));
        language = Language.parseText(langconfig, "Language");
    }

    @SuppressWarnings("unchecked")
    public synchronized boolean loadYml() throws Exception {
        final File saveFolder = new File(dataFolder, "Save");
        try {
            final File worldFolder = new File(saveFolder, "Worlds");
            if (!saveFolder.isDirectory()) {
                this.getLogger().warning("领地数据保存目录不存在 跳过载入...");
                return true;
            }
            YMLSaveHelper yml;
            File loadFile;
            final long time = System.currentTimeMillis();
            final HashMap<String, Object> worlds = new HashMap<>();
            for (final World world : this.getServer().getWorlds()) {
                loadFile = new File(worldFolder, "res_" + world.getName() + ".yml");
                if (loadFile.isFile()) {
                    yml = new YMLSaveHelper(loadFile);
                    yml.load();
                    worlds.put(world.getName(), yml.getRoot().get("Residences"));
                }
            }
            rmanager = ResidenceManager.load(this, worlds);
            loadFile = new File(saveFolder, "forsale.yml");
            if (loadFile.isFile()) {
                yml = new YMLSaveHelper(loadFile);
                yml.load();
                tmanager = TransactionManager.load(this, (Map<?, ?>) yml.getRoot().get("Economy"), gmanager, rmanager);
            }
            loadFile = new File(saveFolder, "leases.yml");
            if (loadFile.isFile()) {
                yml = new YMLSaveHelper(loadFile);
                yml.load();
                leasemanager = LeaseManager.load(this, (Map<String, Long>) yml.getRoot().get("Leases"), rmanager);
            }
            loadFile = new File(saveFolder, "permlists.yml");
            if (loadFile.isFile()) {
                yml = new YMLSaveHelper(loadFile);
                yml.load();
                pmanager = PermissionListManager.load(this, (Map<String, Object>) yml.getRoot().get("PermissionLists"));
            }
            loadFile = new File(saveFolder, "rent.yml");
            if (loadFile.isFile()) {
                yml = new YMLSaveHelper(loadFile);
                yml.load();
                rentmanager = RentManager.load(this, (Map<String, Object>) yml.getRoot().get("RentSystem"));
            }
            this.getLogger().info("从配置文件中读取领地数据完毕,耗时 " + ((float) (System.currentTimeMillis() - time) / 1000) + " 秒");
            return true;
        } catch (final Exception ex) {
            this.getLogger().warning("领地数据载入时发生错误,请报告以下内容给作者: ");
            this.getLogger().warning("错误: " + ex);
            throw ex;
        }
    }

    @Override
    public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
        final ResidenceCommandEvent cevent = new ResidenceCommandEvent(command.getName(), args, sender);
        this.getServer().getPluginManager().callEvent(cevent);
        if (cevent.isCancelled()) {
            return true;
        }
        if (args.length == 0) {
            return hdmcnd.onCommand(sender, command, label, new String[] { "?" });
        }
        return hdmcnd.onCommand(sender, command, label, args);
    }

    @Override
    public void onDisable() {
        if (this.init) {
            taskmanager.cancelall();
            try {
                this.saveYml();
                this.backup.backup();
            } catch (final Exception ex) {
                this.getLogger().warning("领地数据保存错误,可能造成部分领地丢失,请尝试恢复备份文件!");
                this.getLogger().warning("错误: " + ex);
            }
        }
    }

    @Override
    public void onEnable() {
        try {
            instance = this;
            init = false;
            FlagPermissions.init(this);
            this.getLogger().info("Bukkit 版本: " + this.getServer().getBukkitVersion());
            try {
                Class.forName("org.bukkit.event.player.PlayerInteractAtEntityEvent");
                vergt1_8 = true;
            } catch (final Exception e) {
                vergt1_8 = false;
            }
            deleteConfirm = new HashMap<>();
            resadminToggle = new ArrayList<>();
            dataFolder = this.getDataFolder();
            if (!dataFolder.isDirectory()) {
                dataFolder.mkdirs();
            }
            cmanager = (new ConfigManager(this));
            final String multiworld = cmanager.getMultiworldPlugin();
            if (multiworld != null) {
                final Plugin plugin = this.getServer().getPluginManager().getPlugin(multiworld);
                if (plugin != null) {
                    if (!plugin.isEnabled()) {
                        this.getLogger().info("加载多世界插件: " + multiworld);
                        this.getServer().getPluginManager().enablePlugin(plugin);
                    }
                }
            }
            fmanager = new FlagUtil(this);
            getFlagUtilManager().load();
            gmanager = new PermissionManager(this);
            imanager = new WorldItemManager(this.getConfig());
            wmanager = new WorldFlagManager(this);
            entitymanager = new EntityManager(this);
            chatmanager = new ChatManager(this);
            rentmanager = new RentManager(this);
            for (final String lang : validLanguages) {
                try {
                    if (this.checkNewLanguageVersion(lang)) {
                        this.writeDefaultLanguageFile(lang);
                    }
                } catch (final Exception ex) {
                    this.getLogger().warning("语言文件升级失败: " + lang + ".yml");
                    helppages = new HelpEntry(this, "");
                    language = new Language();
                }
            }
            final File langFile = new File(new File(dataFolder, "Language"), cmanager.getLanguage() + ".yml");
            try {
                if (langFile.isFile()) {
                    loadLang(langFile);
                } else {
                    this.getLogger().warning("语言文件不存在...");
                }
            } catch (final Exception ex) {
                this.getLogger().warning("语言文件载入失败: " + cmanager.getLanguage() + ".yml 写入默认语言文件");
                this.writeDefaultLanguageFile(cmanager.getLanguage());
                loadLang(langFile);
            }
            economy = null;
            if (this.getConfig().getBoolean("Global.EnableEconomy", false)) {
                if (gmanager.getPermissionsPlugin() instanceof ResidenceVaultAdapter) {
                    final ResidenceVaultAdapter vault = (ResidenceVaultAdapter) gmanager.getPermissionsPlugin();
                    if (vault.economyOK()) {
                        economy = vault;
                        this.getLogger().info("发现 Vault 使用经济系统: " + vault.getEconomyName());
                    }
                }
                if (economy == null) {
                    this.loadVaultEconomy();
                }
                if (economy == null) {
                    this.loadEssentialsEconomy();
                }
                if (economy == null) {
                    this.getLogger().warning("经济系统已启用,但是未找到经济插件...");
                }
            }
            try {
                this.loadYml();
            } catch (final Exception e) {
                this.getLogger().warning("领地数据载入错误,可能造成插件无法启动,请尝试恢复备份文件!");
                this.getLogger().warning("错误: " + e);
            }
            if (rmanager == null) {
                rmanager = new ResidenceManager(this);
            }
            if (leasemanager == null) {
                leasemanager = new LeaseManager(this, rmanager);
            }
            if (tmanager == null) {
                tmanager = new TransactionManager(this, rmanager, gmanager);
            }
            if (pmanager == null) {
                pmanager = new PermissionListManager(this);
            }
            if (taskmanager == null) {
                taskmanager = new TaskManager(this);
            }
            final PluginManager pm = getServer().getPluginManager();

            if (!this.isEnabled()) {
                return;
            }
            FlagPermissions.initValidFlags();
            final Plugin wep = this.getServer().getPluginManager().getPlugin("WorldEdit");
            if (wep != null) {
                smanager = new WorldEditSelectionManager(this);
                useWorldEdit = true;
                this.getLogger().info("发现 WorldEdit 已启用相关支持...");
            } else {
                smanager = new SelectionManager(this);
                useWorldEdit = false;
            }
            blistener = new ResidenceBlockListener(this);
            plistener = new ResidencePlayerListener(this);
            elistener = new ResidenceEntityListener(this);
            plistener1_8 = new ResidencePlayerListener_1_8(this);
            glistener = new ResidenceGUIListener();
            pm.registerEvents(blistener, this);
            pm.registerEvents(plistener, this);
            if (isGt1_8()) {
                pm.registerEvents(plistener1_8, this);
            }
            pm.registerEvents(elistener, this);
            pm.registerEvents(glistener, this);

            this.getLogger().info("开始加载领地补丁...");
            pm.registerEvents(new ResidenceBugFix(this), this);

            taskmanager.add(this.getServer().getScheduler().runTaskTimer(this, new HealTask(this), 20, 20));

            hdmcnd = new HandlerMainCommand(this);
            hdmcnd.registerCommand(new CommandRc(this));
            hdmcnd.registerCommand(new CommandRes(this));
            hdmcnd.registerCommand(new CommandResLoad(this));
            hdmcnd.registerCommand(new CommandResReload(this));
            hdmcnd.registerCommand(new CommandResWorld(this));

            int autosaveInt = cmanager.getAutoSaveInterval();
            autosaveInt = autosaveInt < 1 ? 1 : autosaveInt * 60 * 20;
            taskmanager.add(this.getServer().getScheduler().runTaskTimerAsynchronously(this, new AutoSaveTask(this), autosaveInt, autosaveInt));

            if (cmanager.useLeases()) {
                int leaseInterval = cmanager.getLeaseCheckInterval();
                leaseInterval = leaseInterval < 1 ? 1 : leaseInterval * 60 * 20;
                taskmanager.add(this.getServer().getScheduler().runTaskTimerAsynchronously(this, new LeaseTask(this), leaseInterval, leaseInterval));
            }
            if (cmanager.enabledRentSystem()) {
                int rentint = cmanager.getRentCheckInterval();
                rentint = rentint < 1 ? 1 : rentint * 60 * 20;
                taskmanager.add(this.getServer().getScheduler().runTaskTimerAsynchronously(this, new RentTask(this), rentint, rentint));
            }
            for (final Player player : CompatibleUtil.getOnlinePlayers()) {
                if (this.getPermissionManager().isResidenceAdmin(player)) {
                    turnResAdminOn(player);
                }
            }
            this.getLogger().info("载入完成! 版本: " + this.getDescription().getVersion() + " 重制 by 喵♂呜");
            backup = new DataBackup(this);
            init = true;
        } catch (final Exception ex) {
            this.getServer().getPluginManager().disablePlugin(this);
            csm("§4初始化失败! 卸载插件! 请报告以下错误给作者,谢谢!");
            csm("§c错误: " + ex);
            ex.printStackTrace();
            return;
        } catch (final Error ex) {
            csm("§c##############################");
            csm("§c领地插件重载失败 请重启服务器!");
            csm("§c领地插件重载失败 请重启服务器!");
            csm("§c领地插件重载失败 请重启服务器!");
            csm("§c##############################");
        }
        try {
            new Residence(this);
            this.getLogger().info("旧版本兼容接口初始化成功...");
        } catch (final LinkageError e) {
            this.csm("§c旧版本兼容接口初始化失败 可能导致部分插件不可用!");
            this.csm("§c若是其他插件重载本插件 请尝试重启服务器修复此问题!");
        }
        new VersionChecker(this);
    }

    @Override
    public void onLoad() {
        config = new FileConfig(this);
        deny = new FileConfig(this, "deny.yml");
    }

    @Override
    public void reloadConfig() {
        config.reload();
        deny.reload();
        gmanager = new PermissionManager(this);
        imanager = new WorldItemManager(this.getConfig());
        wmanager = new WorldFlagManager(this);
        entitymanager = new EntityManager(this);
        chatmanager = new ChatManager(this);
        rentmanager = new RentManager(this);
    }

    public void reloadPlugin() {
        final PluginManager pm = this.getServer().getPluginManager();
        pm.disablePlugin(this);
        pm.enablePlugin(this);
    }

    @Override
    public void saveConfig() {
        config.save();
    };

    public synchronized void saveYml() throws IOException {
        final File saveFolder = new File(dataFolder, "Save");
        final File worldFolder = new File(saveFolder, "Worlds");
        worldFolder.mkdirs();
        YMLSaveHelper yml;
        final long time = System.currentTimeMillis();
        final Map<String, Object> save = rmanager.save();
        for (final Entry<String, Object> entry : save.entrySet()) {
            final File ymlSaveLoc = new File(worldFolder, "res_" + entry.getKey() + ".yml");
            final File tmpFile = new File(worldFolder, "tmp_res_" + entry.getKey() + ".yml");
            yml = new YMLSaveHelper(tmpFile);
            yml.getRoot().put("Version", saveVersion);
            final World world = this.getServer().getWorld(entry.getKey());
            if (world != null) {
                yml.getRoot().put("Seed", world.getSeed());
            }
            yml.getRoot().put("Residences", entry.getValue());
            yml.save();
            if (ymlSaveLoc.isFile()) {
                final File backupFolder = new File(worldFolder, "Backup");
                backupFolder.mkdirs();
                final File backupFile = new File(backupFolder, "res_" + entry.getKey() + ".yml");
                if (backupFile.isFile()) {
                    backupFile.delete();
                }
                ymlSaveLoc.renameTo(backupFile);
            }
            tmpFile.renameTo(ymlSaveLoc);
        }

        // For Sale save
        File ymlSaveLoc = new File(saveFolder, "forsale.yml");
        File tmpFile = new File(saveFolder, "tmp_forsale.yml");
        yml = new YMLSaveHelper(tmpFile);
        yml.getRoot().put("Version", saveVersion);
        yml.getRoot().put("Economy", tmanager.save());
        yml.save();
        if (ymlSaveLoc.isFile()) {
            final File backupFolder = new File(saveFolder, "Backup");
            backupFolder.mkdirs();
            final File backupFile = new File(backupFolder, "forsale.yml");
            if (backupFile.isFile()) {
                backupFile.delete();
            }
            ymlSaveLoc.renameTo(backupFile);
        }
        tmpFile.renameTo(ymlSaveLoc);

        // Leases save
        ymlSaveLoc = new File(saveFolder, "leases.yml");
        tmpFile = new File(saveFolder, "tmp_leases.yml");
        yml = new YMLSaveHelper(tmpFile);
        yml.getRoot().put("Version", saveVersion);
        yml.getRoot().put("Leases", leasemanager.save());
        yml.save();
        if (ymlSaveLoc.isFile()) {
            final File backupFolder = new File(saveFolder, "Backup");
            backupFolder.mkdirs();
            final File backupFile = new File(backupFolder, "leases.yml");
            if (backupFile.isFile()) {
                backupFile.delete();
            }
            ymlSaveLoc.renameTo(backupFile);
        }
        tmpFile.renameTo(ymlSaveLoc);

        // permlist save
        ymlSaveLoc = new File(saveFolder, "permlists.yml");
        tmpFile = new File(saveFolder, "tmp_permlists.yml");
        yml = new YMLSaveHelper(tmpFile);
        yml.getRoot().put("Version", saveVersion);
        yml.getRoot().put("PermissionLists", pmanager.save());
        yml.save();
        if (ymlSaveLoc.isFile()) {
            final File backupFolder = new File(saveFolder, "Backup");
            backupFolder.mkdirs();
            final File backupFile = new File(backupFolder, "permlists.yml");
            if (backupFile.isFile()) {
                backupFile.delete();
            }
            ymlSaveLoc.renameTo(backupFile);
        }
        tmpFile.renameTo(ymlSaveLoc);

        // rent save
        ymlSaveLoc = new File(saveFolder, "rent.yml");
        tmpFile = new File(saveFolder, "tmp_rent.yml");
        yml = new YMLSaveHelper(tmpFile);
        yml.getRoot().put("Version", saveVersion);
        yml.getRoot().put("RentSystem", rentmanager.save());
        yml.save();
        if (ymlSaveLoc.isFile()) {
            final File backupFolder = new File(saveFolder, "Backup");
            backupFolder.mkdirs();
            final File backupFile = new File(backupFolder, "rent.yml");
            if (backupFile.isFile()) {
                backupFile.delete();
            }
            ymlSaveLoc.renameTo(backupFile);
        }
        tmpFile.renameTo(ymlSaveLoc);
        this.getLogger().info("保存领地数据到文件中,耗时 " + ((float) (System.currentTimeMillis() - time) / 1000) + " 秒");
        if (cmanager.showIntervalMessages()) {
            this.getLogger().info(" - 保存插件数据...");
        }
    }

    public void setLanguage(final Language language) {
        this.language = language;
    }

    public void turnResAdminOn(final Player player) {
        resadminToggle.add(player.getName());
    }

    public boolean validName(final String name) {
        if (name.contains(":") || name.contains(".")) {
            return false;
        }
        if (cmanager.getResidenceNameRegex() == null) {
            return true;
        }
        final String namecheck = name.replaceAll(cmanager.getResidenceNameRegex(), "");
        if (!name.equals(namecheck)) {
            return false;
        }
        return true;
    }

    private boolean checkNewLanguageVersion(final String lang) throws IOException, FileNotFoundException, InvalidConfigurationException {
        final File outFile = new File(new File(this.getDataFolder(), "Language"), lang + ".yml");
        final File checkFile = new File(new File(this.getDataFolder(), "Language"), "temp-" + lang + ".yml");
        if (outFile.isFile()) {
            final FileConfig testconfig = new FileConfig(this, outFile);
            final int oldversion = testconfig.getInt("FieldsVersion", 0);
            if (!this.writeDefaultFileFromJar(checkFile, "languagefiles/" + lang + ".yml", false)) {
                return false;
            }
            final FileConfig testconfig2 = new FileConfig(this, checkFile);
            testconfig2.load(checkFile);
            final int newversion = testconfig2.getInt("FieldsVersion", oldversion);
            if (checkFile.isFile()) {
                checkFile.delete();
            }
            if (newversion > oldversion) {
                return true;
            }
            return false;
        }
        return true;
    }

    private void loadEssentialsEconomy() {
        final Plugin p = getServer().getPluginManager().getPlugin("Essentials");
        if (p != null) {
            economy = new EssentialsEcoAdapter((Essentials) p);
            this.getLogger().info("成功关联Essentials Economy!");
        } else {
            this.getLogger().info("Essentials Economy 未找到!");
        }
    }

    private void loadVaultEconomy() {
        final Plugin p = getServer().getPluginManager().getPlugin("Vault");
        if (p != null) {
            final ResidenceVaultAdapter vault = new ResidenceVaultAdapter(getServer());
            if (vault.economyOK()) {
                this.getLogger().info("发现 Vault 使用经济系统: " + vault.getEconomyName());
                economy = vault;
            } else {
                this.getLogger().info("发现 Vault, 但是 Vault 未找到经济系统...");
            }
        } else {
            this.getLogger().info("Vault 未找到!");
        }
    }

    @SuppressWarnings("resource")
    private boolean writeDefaultFileFromJar(final File writeName, final String jarPath, final boolean backupOld) {
        try {
            final File fileBackup = new File(this.getDataFolder(), "backup-" + writeName);
            final File jarloc = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getCanonicalFile();
            if (jarloc.isFile()) {
                final JarFile jar = new JarFile(jarloc);
                final JarEntry entry = jar.getJarEntry(jarPath);
                if (entry != null && !entry.isDirectory()) {
                    final InputStream in = jar.getInputStream(entry);
                    final InputStreamReader isr = new InputStreamReader(in, "UTF8");
                    if (writeName.isFile()) {
                        if (backupOld) {
                            if (fileBackup.isFile()) {
                                fileBackup.delete();
                            }
                            writeName.renameTo(fileBackup);
                        } else {
                            writeName.delete();
                        }
                    }
                    final FileOutputStream out = new FileOutputStream(writeName);
                    final OutputStreamWriter osw = new OutputStreamWriter(out, "UTF8");
                    final char[] tempbytes = new char[512];
                    int readbytes = isr.read(tempbytes, 0, 512);
                    while (readbytes > -1) {
                        osw.write(tempbytes, 0, readbytes);
                        readbytes = isr.read(tempbytes, 0, 512);
                    }
                    osw.close();
                    isr.close();
                    return true;
                }
            }
            return false;
        } catch (final Exception ex) {
            this.getLogger().warning("文件写入失败: " + writeName);
            return false;
        }
    }

    private void writeDefaultLanguageFile(final String lang) {
        final File outFile = new File(new File(this.getDataFolder(), "Language"), lang + ".yml");
        outFile.getParentFile().mkdirs();
        if (this.writeDefaultFileFromJar(outFile, "languagefiles/" + lang + ".yml", true)) {
            this.getLogger().info("保存默认 " + lang + " 语言文件...");
        }
    }
}
